#ifndef     __OMNI_SCHEDULER_H_INCLUDED__
#define     __OMNI_SCHEDULER_H_INCLUDED__

#include    <cstdint>
#include    <functional>
#include    <list>
#include    <string>

/**
 * Timer and Dialy schedule task manager.
 */
class Scheduler {

    /** Task definition */
    struct Task {
        uint64_t id;        //! Unique id to access this task
        bool cancelled;     //! Has this job been cancelled?
        double trigger;     //! Next trigger time
        double loop_delay;  //! Loop delay. >0 valid
        int proc;           //! Job function reference id in Lua VM.
    };

public:
    Scheduler();
    ~Scheduler();

    /**
     * Get runtime singleton instance
     */
    static Scheduler & Instance();

    /**
     * Add timer task.
     * 
     * \param delay Delay time in milliseconds to run this job.
     * \param proc Job to do.
     * \param loop Optional. Pass true to enable looping.
     * \return Task id for future access.
     */
    uint64_t Add(double delay, int proc, bool loop = false);

    /**
     * Add daily schedule task.
     * 
     * \param hour Hour[0, 23]
     * \param minute Minute[0, 59]
     * \param second Second[0, 59]
     * \param proc Job to do.
     * \return Task id for future access.
     */
    uint64_t Add(int hour, int minute, int second, int proc);

    /**
     * Is an timer/daily task on schedule.
     */
    bool IsValid(uint64_t id);

    /**
     * Get remain time in milliseconds before running this job
     */
    double GetRemainTime(uint64_t id);

    /**
     * Cancel a timer/daily task
     */
    void Cancel(uint64_t id);

    /**
     * Tick manager once time.
     */
    void Breath(struct lua_State * lua);

private:
    uint64_t __Add(double trigger, double loop, int proc);

private:
    uint64_t _alloc_id;
    double _next;
    std::list<Task *> _tasks;
};

#endif//!   __OMNI_SCHEDULER_H_INCLUDED__